/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controladoresJPA;

import controladoresJPA.exceptions.NonexistentEntityException;
import controladoresJPA.exceptions.RollbackFailureException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import modelo.Categoria;
import modelo.Usuario;
import modelo.Consumidor;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import javax.transaction.UserTransaction;
import modelo.Consumible;
import modelo.Ingreso;
import modelo.Persona;

/**
 *
 * @author Francisco
 */
public class CategoriaJpaController implements Serializable {

    public CategoriaJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Categoria categoria) throws RollbackFailureException, Exception {
        if (categoria.getConsumidorList() == null) {
            categoria.setConsumidorList(new ArrayList<Consumidor>());
        }
        if (categoria.getConsumibleList() == null) {
            categoria.setConsumibleList(new ArrayList<Consumible>());
        }
        if (categoria.getIngresoList() == null) {
            categoria.setIngresoList(new ArrayList<Ingreso>());
        }
        if (categoria.getPersonaList() == null) {
            categoria.setPersonaList(new ArrayList<Persona>());
        }
        if (categoria.getCategoriaList() == null) {
            categoria.setCategoriaList(new ArrayList<Categoria>());
        }
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Categoria idCategoriaPadre = categoria.getIdCategoriaPadre();
            if (idCategoriaPadre != null) {
                idCategoriaPadre = em.getReference(idCategoriaPadre.getClass(), idCategoriaPadre.getIdCategoria());
                categoria.setIdCategoriaPadre(idCategoriaPadre);
            }
            Usuario idUsuario = categoria.getIdUsuario();
            if (idUsuario != null) {
                idUsuario = em.getReference(idUsuario.getClass(), idUsuario.getIdUsuario());
                categoria.setIdUsuario(idUsuario);
            }
            List<Consumidor> attachedConsumidorList = new ArrayList<Consumidor>();
            for (Consumidor consumidorListConsumidorToAttach : categoria.getConsumidorList()) {
                consumidorListConsumidorToAttach = em.getReference(consumidorListConsumidorToAttach.getClass(), consumidorListConsumidorToAttach.getIdConsumidor());
                attachedConsumidorList.add(consumidorListConsumidorToAttach);
            }
            categoria.setConsumidorList(attachedConsumidorList);
            List<Consumible> attachedConsumibleList = new ArrayList<Consumible>();
            for (Consumible consumibleListConsumibleToAttach : categoria.getConsumibleList()) {
                consumibleListConsumibleToAttach = em.getReference(consumibleListConsumibleToAttach.getClass(), consumibleListConsumibleToAttach.getIdConsumible());
                attachedConsumibleList.add(consumibleListConsumibleToAttach);
            }
            categoria.setConsumibleList(attachedConsumibleList);
            List<Ingreso> attachedIngresoList = new ArrayList<Ingreso>();
            for (Ingreso ingresoListIngresoToAttach : categoria.getIngresoList()) {
                ingresoListIngresoToAttach = em.getReference(ingresoListIngresoToAttach.getClass(), ingresoListIngresoToAttach.getIdIngreso());
                attachedIngresoList.add(ingresoListIngresoToAttach);
            }
            categoria.setIngresoList(attachedIngresoList);
            List<Persona> attachedPersonaList = new ArrayList<Persona>();
            for (Persona personaListPersonaToAttach : categoria.getPersonaList()) {
                personaListPersonaToAttach = em.getReference(personaListPersonaToAttach.getClass(), personaListPersonaToAttach.getIdPersona());
                attachedPersonaList.add(personaListPersonaToAttach);
            }
            categoria.setPersonaList(attachedPersonaList);
            List<Categoria> attachedCategoriaList = new ArrayList<Categoria>();
            for (Categoria categoriaListCategoriaToAttach : categoria.getCategoriaList()) {
                categoriaListCategoriaToAttach = em.getReference(categoriaListCategoriaToAttach.getClass(), categoriaListCategoriaToAttach.getIdCategoria());
                attachedCategoriaList.add(categoriaListCategoriaToAttach);
            }
            categoria.setCategoriaList(attachedCategoriaList);
            em.persist(categoria);
            if (idCategoriaPadre != null) {
                idCategoriaPadre.getCategoriaList().add(categoria);
                idCategoriaPadre = em.merge(idCategoriaPadre);
            }
            if (idUsuario != null) {
                idUsuario.getCategoriaList().add(categoria);
                idUsuario = em.merge(idUsuario);
            }
            for (Consumidor consumidorListConsumidor : categoria.getConsumidorList()) {
                consumidorListConsumidor.getCategoriaList().add(categoria);
                consumidorListConsumidor = em.merge(consumidorListConsumidor);
            }
            for (Consumible consumibleListConsumible : categoria.getConsumibleList()) {
                consumibleListConsumible.getCategoriaList().add(categoria);
                consumibleListConsumible = em.merge(consumibleListConsumible);
            }
            for (Ingreso ingresoListIngreso : categoria.getIngresoList()) {
                ingresoListIngreso.getCategoriaList().add(categoria);
                ingresoListIngreso = em.merge(ingresoListIngreso);
            }
            for (Persona personaListPersona : categoria.getPersonaList()) {
                personaListPersona.getCategoriaList().add(categoria);
                personaListPersona = em.merge(personaListPersona);
            }
            for (Categoria categoriaListCategoria : categoria.getCategoriaList()) {
                Categoria oldIdCategoriaPadreOfCategoriaListCategoria = categoriaListCategoria.getIdCategoriaPadre();
                categoriaListCategoria.setIdCategoriaPadre(categoria);
                categoriaListCategoria = em.merge(categoriaListCategoria);
                if (oldIdCategoriaPadreOfCategoriaListCategoria != null) {
                    oldIdCategoriaPadreOfCategoriaListCategoria.getCategoriaList().remove(categoriaListCategoria);
                    oldIdCategoriaPadreOfCategoriaListCategoria = em.merge(oldIdCategoriaPadreOfCategoriaListCategoria);
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Categoria categoria) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Categoria persistentCategoria = em.find(Categoria.class, categoria.getIdCategoria());
            Categoria idCategoriaPadreOld = persistentCategoria.getIdCategoriaPadre();
            Categoria idCategoriaPadreNew = categoria.getIdCategoriaPadre();
            Usuario idUsuarioOld = persistentCategoria.getIdUsuario();
            Usuario idUsuarioNew = categoria.getIdUsuario();
            List<Consumidor> consumidorListOld = persistentCategoria.getConsumidorList();
            List<Consumidor> consumidorListNew = categoria.getConsumidorList();
            List<Consumible> consumibleListOld = persistentCategoria.getConsumibleList();
            List<Consumible> consumibleListNew = categoria.getConsumibleList();
            List<Ingreso> ingresoListOld = persistentCategoria.getIngresoList();
            List<Ingreso> ingresoListNew = categoria.getIngresoList();
            List<Persona> personaListOld = persistentCategoria.getPersonaList();
            List<Persona> personaListNew = categoria.getPersonaList();
            List<Categoria> categoriaListOld = persistentCategoria.getCategoriaList();
            List<Categoria> categoriaListNew = categoria.getCategoriaList();
            if (idCategoriaPadreNew != null) {
                idCategoriaPadreNew = em.getReference(idCategoriaPadreNew.getClass(), idCategoriaPadreNew.getIdCategoria());
                categoria.setIdCategoriaPadre(idCategoriaPadreNew);
            }
            if (idUsuarioNew != null) {
                idUsuarioNew = em.getReference(idUsuarioNew.getClass(), idUsuarioNew.getIdUsuario());
                categoria.setIdUsuario(idUsuarioNew);
            }
            List<Consumidor> attachedConsumidorListNew = new ArrayList<Consumidor>();
            for (Consumidor consumidorListNewConsumidorToAttach : consumidorListNew) {
                consumidorListNewConsumidorToAttach = em.getReference(consumidorListNewConsumidorToAttach.getClass(), consumidorListNewConsumidorToAttach.getIdConsumidor());
                attachedConsumidorListNew.add(consumidorListNewConsumidorToAttach);
            }
            consumidorListNew = attachedConsumidorListNew;
            categoria.setConsumidorList(consumidorListNew);
            List<Consumible> attachedConsumibleListNew = new ArrayList<Consumible>();
            for (Consumible consumibleListNewConsumibleToAttach : consumibleListNew) {
                consumibleListNewConsumibleToAttach = em.getReference(consumibleListNewConsumibleToAttach.getClass(), consumibleListNewConsumibleToAttach.getIdConsumible());
                attachedConsumibleListNew.add(consumibleListNewConsumibleToAttach);
            }
            consumibleListNew = attachedConsumibleListNew;
            categoria.setConsumibleList(consumibleListNew);
            List<Ingreso> attachedIngresoListNew = new ArrayList<Ingreso>();
            for (Ingreso ingresoListNewIngresoToAttach : ingresoListNew) {
                ingresoListNewIngresoToAttach = em.getReference(ingresoListNewIngresoToAttach.getClass(), ingresoListNewIngresoToAttach.getIdIngreso());
                attachedIngresoListNew.add(ingresoListNewIngresoToAttach);
            }
            ingresoListNew = attachedIngresoListNew;
            categoria.setIngresoList(ingresoListNew);
            List<Persona> attachedPersonaListNew = new ArrayList<Persona>();
            for (Persona personaListNewPersonaToAttach : personaListNew) {
                personaListNewPersonaToAttach = em.getReference(personaListNewPersonaToAttach.getClass(), personaListNewPersonaToAttach.getIdPersona());
                attachedPersonaListNew.add(personaListNewPersonaToAttach);
            }
            personaListNew = attachedPersonaListNew;
            categoria.setPersonaList(personaListNew);
            List<Categoria> attachedCategoriaListNew = new ArrayList<Categoria>();
            for (Categoria categoriaListNewCategoriaToAttach : categoriaListNew) {
                categoriaListNewCategoriaToAttach = em.getReference(categoriaListNewCategoriaToAttach.getClass(), categoriaListNewCategoriaToAttach.getIdCategoria());
                attachedCategoriaListNew.add(categoriaListNewCategoriaToAttach);
            }
            categoriaListNew = attachedCategoriaListNew;
            categoria.setCategoriaList(categoriaListNew);
            categoria = em.merge(categoria);
            if (idCategoriaPadreOld != null && !idCategoriaPadreOld.equals(idCategoriaPadreNew)) {
                idCategoriaPadreOld.getCategoriaList().remove(categoria);
                idCategoriaPadreOld = em.merge(idCategoriaPadreOld);
            }
            if (idCategoriaPadreNew != null && !idCategoriaPadreNew.equals(idCategoriaPadreOld)) {
                idCategoriaPadreNew.getCategoriaList().add(categoria);
                idCategoriaPadreNew = em.merge(idCategoriaPadreNew);
            }
            if (idUsuarioOld != null && !idUsuarioOld.equals(idUsuarioNew)) {
                idUsuarioOld.getCategoriaList().remove(categoria);
                idUsuarioOld = em.merge(idUsuarioOld);
            }
            if (idUsuarioNew != null && !idUsuarioNew.equals(idUsuarioOld)) {
                idUsuarioNew.getCategoriaList().add(categoria);
                idUsuarioNew = em.merge(idUsuarioNew);
            }
            for (Consumidor consumidorListOldConsumidor : consumidorListOld) {
                if (!consumidorListNew.contains(consumidorListOldConsumidor)) {
                    consumidorListOldConsumidor.getCategoriaList().remove(categoria);
                    consumidorListOldConsumidor = em.merge(consumidorListOldConsumidor);
                }
            }
            for (Consumidor consumidorListNewConsumidor : consumidorListNew) {
                if (!consumidorListOld.contains(consumidorListNewConsumidor)) {
                    consumidorListNewConsumidor.getCategoriaList().add(categoria);
                    consumidorListNewConsumidor = em.merge(consumidorListNewConsumidor);
                }
            }
            for (Consumible consumibleListOldConsumible : consumibleListOld) {
                if (!consumibleListNew.contains(consumibleListOldConsumible)) {
                    consumibleListOldConsumible.getCategoriaList().remove(categoria);
                    consumibleListOldConsumible = em.merge(consumibleListOldConsumible);
                }
            }
            for (Consumible consumibleListNewConsumible : consumibleListNew) {
                if (!consumibleListOld.contains(consumibleListNewConsumible)) {
                    consumibleListNewConsumible.getCategoriaList().add(categoria);
                    consumibleListNewConsumible = em.merge(consumibleListNewConsumible);
                }
            }
            for (Ingreso ingresoListOldIngreso : ingresoListOld) {
                if (!ingresoListNew.contains(ingresoListOldIngreso)) {
                    ingresoListOldIngreso.getCategoriaList().remove(categoria);
                    ingresoListOldIngreso = em.merge(ingresoListOldIngreso);
                }
            }
            for (Ingreso ingresoListNewIngreso : ingresoListNew) {
                if (!ingresoListOld.contains(ingresoListNewIngreso)) {
                    ingresoListNewIngreso.getCategoriaList().add(categoria);
                    ingresoListNewIngreso = em.merge(ingresoListNewIngreso);
                }
            }
            for (Persona personaListOldPersona : personaListOld) {
                if (!personaListNew.contains(personaListOldPersona)) {
                    personaListOldPersona.getCategoriaList().remove(categoria);
                    personaListOldPersona = em.merge(personaListOldPersona);
                }
            }
            for (Persona personaListNewPersona : personaListNew) {
                if (!personaListOld.contains(personaListNewPersona)) {
                    personaListNewPersona.getCategoriaList().add(categoria);
                    personaListNewPersona = em.merge(personaListNewPersona);
                }
            }
            for (Categoria categoriaListOldCategoria : categoriaListOld) {
                if (!categoriaListNew.contains(categoriaListOldCategoria)) {
                    categoriaListOldCategoria.setIdCategoriaPadre(null);
                    categoriaListOldCategoria = em.merge(categoriaListOldCategoria);
                }
            }
            for (Categoria categoriaListNewCategoria : categoriaListNew) {
                if (!categoriaListOld.contains(categoriaListNewCategoria)) {
                    Categoria oldIdCategoriaPadreOfCategoriaListNewCategoria = categoriaListNewCategoria.getIdCategoriaPadre();
                    categoriaListNewCategoria.setIdCategoriaPadre(categoria);
                    categoriaListNewCategoria = em.merge(categoriaListNewCategoria);
                    if (oldIdCategoriaPadreOfCategoriaListNewCategoria != null && !oldIdCategoriaPadreOfCategoriaListNewCategoria.equals(categoria)) {
                        oldIdCategoriaPadreOfCategoriaListNewCategoria.getCategoriaList().remove(categoriaListNewCategoria);
                        oldIdCategoriaPadreOfCategoriaListNewCategoria = em.merge(oldIdCategoriaPadreOfCategoriaListNewCategoria);
                    }
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = categoria.getIdCategoria();
                if (findCategoria(id) == null) {
                    throw new NonexistentEntityException("The categoria with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Categoria categoria;
            try {
                categoria = em.getReference(Categoria.class, id);
                categoria.getIdCategoria();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The categoria with id " + id + " no longer exists.", enfe);
            }
            Categoria idCategoriaPadre = categoria.getIdCategoriaPadre();
            if (idCategoriaPadre != null) {
                idCategoriaPadre.getCategoriaList().remove(categoria);
                idCategoriaPadre = em.merge(idCategoriaPadre);
            }
            Usuario idUsuario = categoria.getIdUsuario();
            if (idUsuario != null) {
                idUsuario.getCategoriaList().remove(categoria);
                idUsuario = em.merge(idUsuario);
            }
            List<Consumidor> consumidorList = categoria.getConsumidorList();
            for (Consumidor consumidorListConsumidor : consumidorList) {
                consumidorListConsumidor.getCategoriaList().remove(categoria);
                consumidorListConsumidor = em.merge(consumidorListConsumidor);
            }
            List<Consumible> consumibleList = categoria.getConsumibleList();
            for (Consumible consumibleListConsumible : consumibleList) {
                consumibleListConsumible.getCategoriaList().remove(categoria);
                consumibleListConsumible = em.merge(consumibleListConsumible);
            }
            List<Ingreso> ingresoList = categoria.getIngresoList();
            for (Ingreso ingresoListIngreso : ingresoList) {
                ingresoListIngreso.getCategoriaList().remove(categoria);
                ingresoListIngreso = em.merge(ingresoListIngreso);
            }
            List<Persona> personaList = categoria.getPersonaList();
            for (Persona personaListPersona : personaList) {
                personaListPersona.getCategoriaList().remove(categoria);
                personaListPersona = em.merge(personaListPersona);
            }
            List<Categoria> categoriaList = categoria.getCategoriaList();
            for (Categoria categoriaListCategoria : categoriaList) {
                categoriaListCategoria.setIdCategoriaPadre(null);
                categoriaListCategoria = em.merge(categoriaListCategoria);
            }
            em.remove(categoria);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Categoria> findCategoriaEntities() {
        return findCategoriaEntities(true, -1, -1);
    }

    public List<Categoria> findCategoriaEntities(int maxResults, int firstResult) {
        return findCategoriaEntities(false, maxResults, firstResult);
    }

    private List<Categoria> findCategoriaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Categoria.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Categoria findCategoria(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Categoria.class, id);
        } finally {
            em.close();
        }
    }
    
    public Categoria findCategoriaByNombre(String nomCat, Integer idUsuario) {
        EntityManager em = getEntityManager();
        try {
            TypedQuery<Categoria> tq = em.createQuery("Select c from Categoria c where c.nombre = :nomCat "
                    + "and c.idUsuario.idUsuario = :idUsu and c.estatus = 'A'", Categoria.class);
            tq.setParameter("nomCat", nomCat);
            tq.setParameter("idUsu", idUsuario);
            return tq.getSingleResult();
        } finally {
            em.close();
        }
    }
    
    public List<Categoria> findActiveByIdUsuario(Integer idUsuario){
        EntityManager em = getEntityManager();
        try {
            TypedQuery<Categoria> tq = em.createQuery("Select c from Categoria c where c.idUsuario.idUsuario = :idUsu"
                    + " and c.estatus = 'A'", Categoria.class);
            tq.setParameter("idUsu", idUsuario);
            return tq.getResultList();
        } finally {
            em.close();
        }
    }

    public int getCategoriaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Categoria> rt = cq.from(Categoria.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
